package com.netcracker.util.service;

import com.netcracker.db.exception.DBException;
import com.netcracker.entity.Author;
import com.netcracker.entity.Book;
import com.netcracker.entity.record.BookRecord;
import com.netcracker.util.dao.DAOFacade;
import com.netcracker.util.service.exception.DataTransmittingException;
import com.netcracker.util.service.exception.NullDataException;
import com.netcracker.util.service.exception.WrongBookException;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public class BookService {
    
    private DAOFacade daoFacade;
    
    public BookService(DAOFacade daoFacade) {
        this.daoFacade = daoFacade;
    }
    
    public void setDAOFacade(DAOFacade daoFacade) {
        this.daoFacade = daoFacade;
    }
    
    public void addBook(BookRecord book) throws DataTransmittingException, WrongBookException {
        try {
            checkRecord(book);
            daoFacade.getBookDAO().create(book);
        } catch (DBException | IOException ex) {
            throw new DataTransmittingException(ex.getMessage(), ex);
        }
    }
    
    public void updateBook(BookRecord book) throws WrongBookException, DataTransmittingException {
        try {
            checkRecord(book);
            daoFacade.getBookDAO().edit(book);
        } catch (DBException ex) {
            throw new DataTransmittingException(ex.getMessage(), ex);
        }
    }
    
    public void deleteBook(int bookID) throws DataTransmittingException {
        try {
            daoFacade.getGenreDAO().remove(bookID);
        } catch(DBException ex) {
            throw new DataTransmittingException(ex.getMessage(), ex);
        }
    }
    
    public Book readBook(int bookID) throws NullDataException, DataTransmittingException {
        try {
            Book book = daoFacade.getBookDAO().find(bookID);
            if (book == null) throw new NullDataException("Book not found!");
            return book;
        } catch(DBException ex) {
            throw new DataTransmittingException(ex.getMessage(), ex);
        }
    }
     
    private void checkRecord(BookRecord book) throws WrongBookException {
        if (book.getName() == null || book.getDescription() == null || book.getPublicDate() == null)
            throw new WrongBookException("Not all fields of book are filled correct!");
        if (book.getYear() == null || book.getUserID() == null || book.getPublisherID() == null)
            throw new WrongBookException("Not all fields of book are filled correct!");
        if (book.getGenreIDs() == null || book.getLanguageID() == null || book.getAuthorsIDs() == null)
            throw new WrongBookException("Not all fields of book are filled correct!");
        if (book.getFile() == null || book.getImage() == null) 
            throw new WrongBookException("Not all fields of book are filled correct!");
    }
    
    public List<Book> findBooksByPublisher(int pubID) throws NullDataException, DataTransmittingException {
        try {
            List<Book> books = daoFacade.getBookDAO().findByPublisher(pubID);
            if (books == null) throw new NullDataException("Books of this publisher not found!");
            return books;
        } catch(DBException ex) {
            throw new DataTransmittingException(ex.getMessage(), ex);
        }
    }
    
    public List<Book> findBooksByAuthor(String name) throws NullDataException, DataTransmittingException{
        try {
            List<Author> authors = daoFacade.getAuthorDAO().findAuthorByName(name);
            if (authors == null) throw new NullDataException("Author not found!");
            List<Book> books = new ArrayList<>();
            for (Author author : authors) {
                List<Book> temp = daoFacade.getBookDAO().findByAuthor(author.getId());
                if (temp != null) 
                    books.addAll(temp);
            }
            if (books.isEmpty()) throw new NullDataException("Books of this author not found!");
            return books;
        } catch(DBException ex) {
            throw new DataTransmittingException(ex.getMessage(), ex);
        }
    }
    
    public List<Book> findBooksByUser(int userID) throws NullDataException, DataTransmittingException{
        try {
            List<Book> books = daoFacade.getBookDAO().findByUser(userID);
            if (books == null) throw new NullDataException("Books of this user not found!");
            return books;
        } catch(DBException ex) {
            throw new DataTransmittingException(ex.getMessage(), ex);
        }
    }
    
    public List<Book> findBooksByName(String name) throws NullDataException, DataTransmittingException{
        try {
            List<Book> books = daoFacade.getBookDAO().findByName(name);
            if (books == null) throw new NullDataException("Books with this name not found!");
            return books;
        } catch(DBException ex) {
            throw new DataTransmittingException(ex.getMessage(), ex);
        }
    }
    
    public List<Book> findBooksByGenre(int genreID) throws NullDataException, DataTransmittingException{
        try {
            List<Book> books = daoFacade.getBookDAO().findByGenre(genreID);
            if (books == null) throw new NullDataException("Books with this genre not found!");
            return books;
        } catch(DBException ex) {
            throw new DataTransmittingException(ex.getMessage(), ex);
        }
    }
    
    public List<Book> findAllBooks() throws DataTransmittingException, NullDataException {
        try {
            List<Book> books = daoFacade.getBookDAO().findAll();
            if (books == null) throw new NullDataException("Books not found!");
            return books;
        } catch(DBException ex) {
            throw new DataTransmittingException(ex.getMessage(), ex);
        }
    }
    
    public File downloadBookFile(int bookID) throws DataTransmittingException, NullDataException {
        try {
            File bookFile = daoFacade.getBookDAO().findBookFile(bookID);
            if (bookFile == null) throw new NullDataException("BookFile not found!");
            return bookFile;
        } catch(DBException | IOException ex) {
            throw new DataTransmittingException(ex.getMessage(), ex);
        }
    }
    
    public File downloadBookImage(int bookID) throws DataTransmittingException, NullDataException {
        try {
            File bookImage = daoFacade.getBookDAO().findBookImage(bookID);
            if (bookImage == null) throw new NullDataException("BookImage not found!");
            return bookImage;
        } catch(DBException | IOException ex) {
            throw new DataTransmittingException(ex.getMessage(), ex);
        }
    }
    
}